4989: [Usaco2017 Feb]Why Did the Cow Cross the Road

题面:4989: [Usaco2017 Feb]Why Did the Cow Cross the Road

连接

http://www.lydsy.com/JudgeOnline/problem.php?id=4989

题面

上下有两个位置分别对应的序列A、B,长度为n,
两序列为n的一个排列。当Ai == Bj时,上下会连一条边。
你可以选择序列A或者序列B进行旋转任意K步,
如 3 4 1 5 2 旋转两步为 5 2 3 4 1。
求旋转后最小的相交的线段的对数。

输入

The first line of input contains N.
The next N lines describe the order, by breed ID, of fields on one side of the road;
each breed ID is an integer in the range 1…N.
The last N lines describe the order, by breed ID, of the fields on the other side of the road.

输出

Please output the minimum number of crossing pairs of breeds after a cyclic shift of the
fields on one side of the road (either side can be shifted).

样例输入

5

5
4
1
3
2
1
3
2
5
4

样例输出

0

题解

树状数组,然后推一下移动一个数的代价就好了。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;

int d[maxn],c[maxn];
int a[maxn],b[maxn],a2[maxn],b2[maxn];
int n;
int lowbit(int x){
	return x&(-x);
}
void update(int x,int v){
	for(int i=x;i<maxn;i+=lowbit(i)){
		d[i]+=v;
	}
}
long long get(int x){
	long long ans = 0;
	for(int i=x;i;i-=lowbit(i)){
		ans+=d[i];
	}
	return ans;
}
long long solve(int a[],int b[]){
	memset(d,0,sizeof(d));
	memset(c,0,sizeof(c));
	for(int i=1;i<=n;i++){
		c[b[i]]=i;
	}
	for(int i=1;i<=n;i++){
		a[i]=c[a[i]];
	}
	long long ans = 0;
	for(int i=1;i<=n;i++){
		ans+=(n-a[i])-get(a[i]);
		update(a[i],1);
	}
	long long ans2 = ans;
	for(int i=n;i>=1;i--){
		ans=ans-(n-a[i])+(a[i]-1);
		ans2=min(ans2,ans);
	}
	return ans2;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		a2[i]=a[i];
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
		b2[i]=b[i];
	}
	cout<<min(solve(a,b),solve(b2,a2))<<endl;
}
posted @ 2017-08-29 15:30  qscqesze  阅读(519)  评论(0编辑  收藏  举报